package com.ruoyi.common.mytools;


import com.ruoyi.common.utils.StringUtils;
import org.apache.commons.codec.binary.Base64;

import java.io.*;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class myRSA2sign {
    private static final String SIGN_TYPE_RSA2 = "RSA2";
    private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
    private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
    private static final int DEFAULT_BUFFER_SIZE = 8192;
    private static final String charset = "utf-8";
    private static final String privateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCufcMoR5bfV5GiT6dq8xV/35n4PjcF4u/r8HBx9WhOF1/WnEDXn/iNjX4Eki8RtvWAw8/tWLstF+jAlMLF480B1uHy9lpayiDFi3JYtm8S/DWc2sYHcmFEz5W9D7NdPZGlQIlMh3ueASAXiRzDMnEzR/0N+HwZaXEj0WVCXowwWysjcTIt14zuTpjhE4ibkel6urU87FJIs7GmM+NzEVthYRjcWig0USPwsggeQQuqWCrMOlgXU9qAVbeh1YJRXRnUrKw/ClAu/Jfdp0bQkkrd/NmXbYCndAoMG41aIpyU33nxpwCcSMIQpAdNlaBBHmoezWQ/FUc7GEWa/DBrojRDAgMBAAECggEAcEutikGwXiIcLqo2o4S3hGkhzPo1LQukvmIp6501OHSgkBxVOq/QJUE3JbfypOLrUqgyK5ycMWQevbm/M93sNM/W8CcNdTp6Jsgcme0mxMAdvMmrAmXhJYi25Eqzc0FJd2F2OxNCQiiVP7BVG2ZeJdOhjxkovK34S0XadgElFYSyHPWQ4+9geL4KyOUnrv8ATE5Tfl2XgkUpYoe5J8Sv7+GFBiQQE1nhcayYV9g80H7n7qScp8p07+Z7Z5745DV1FBfI5QspFsp+d+/LxvS1iIZNrS6oEyHhW5ke1O/RYngdWkkh1vsqAkj6DfUnDZVJNNj+5sLaTnaPZlbfWotrgQKBgQD+cbaV6jIKycn7nveL1tdkalZ2f9+R7LSAeAmBxCFHQmoyTxj9nkGPr7UPELWYm5U9D81rJLlT+GT7BDRdUfc9OyUI3Qy4pmglmoPlUj1mMgnrmwi5cD4samYcu4wWgDx3rK4HrVwWLT8aj9FgsZakzpz5dIqpt6OVvi09DKZFwQKBgQCvjuWp1TzgixeWfzy6y+L6dJd/nORpyFed81NcGKXfa7TZ5Hy25uvOSFHxIRwahvkE0+fbz4IXOTPEq2fCRHl9P4SDLZ8JuOi1t8PdRgbJMWKj9qZVw0xksmdKWyNTZCJVSzo4cH/ij57y2pP4W+4c0Ah69lRYlzH1PUWXD6YjAwKBgQDGEi1JbINCJK1og+o+YKNR1vmxy391sCcfLtJvwwcI2umiejKBE9YDjYtLy/0hbFPzsb5+Hptqg53QTgiZcLofX1BIIxPJFjlStILiXG/Rgzh3wTs8Z+TuXHFbAqBdz7vCiZj7/vcFiHlsKvKZ7ATSDMjj49YhogPlCKNct+EjwQKBgQCUeHRQki8+80MKmybAD2gxSmNJoGUn9S/sO/m2vH2jmtJDKFI02Mx6E32BQPAkmxuEcrX2luK9Qzo9zHwetoxMWWh3DCEhNslPzU8PFobspiB27ES16Un1K0/heXxBrUDAA7QEQVhWQgI5/pL/irewlFtnqmWg2pV8gsoUvD5UAwKBgQDh+K7dleffF+nC3qiaCerlykoaRFsiH3z6q2J8Zuz0cERHP9t/9ukL2LKVP+M1K9UE2boc7ssqJ2At8yxIURSFCldxzpZWyOH/Zb/jydgjeaUcF39dK11C78cA9ZgWLGHFzS2wojSRcF8Edu2RTvjwla9d01Skzw9r5gSLbHfzGw==";

    /**
     * RSA/RSA2 生成签名
     * @return
     * @throws Exception
     */

    //过程也是：获得秘钥 -> getInstance获得实例 -> initSign初始化 -> update数据 -> sign签名
    public static String rsaSign(String content,byte[] privateKeyBytes) throws Exception {
        PrivateKey priKey = null;
        Signature signature = null;
        //System.out.println("请求参数生成的字符串为:" + content);
        //priKey = getPrivateKeyFromPKCS8("RSA", new ByteArrayInputStream(privateKey.getBytes()));
        priKey = getPrivateKeyFromPKCS8("RSA", new ByteArrayInputStream(privateKeyBytes));
        signature = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
        signature.initSign(priKey);
        signature.update(content.getBytes());
        byte[] signed = signature.sign();
        return new String(Base64.encodeBase64(signed));
    }


    //将私钥从PKC1转换为PKCS8
    public static PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throws Exception {
        if (ins == null || StringUtils.isEmpty(algorithm)) {
            return null;
        }
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        byte[] encodedKey = readText(ins).getBytes();
        encodedKey = Base64.decodeBase64(encodedKey);
        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
    }

    public static PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        StringWriter writer = new StringWriter();
        io(new InputStreamReader(ins), writer, -1);
        byte[] encodedKey = writer.toString().getBytes();
        encodedKey = Base64.decodeBase64(encodedKey);
        return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
    }

    private static String readText(InputStream ins) throws IOException {
        Reader reader = new InputStreamReader(ins);
        StringWriter writer = new StringWriter();
        io(reader, writer, -1);
        return writer.toString();
    }

    private static void io(Reader in, Writer out, int bufferSize) throws IOException {
        if (bufferSize == -1) {
            bufferSize = DEFAULT_BUFFER_SIZE >> 1;
        }
        char[] buffer = new char[bufferSize];
        int amount;
        while ((amount = in.read(buffer)) >= 0) {
            out.write(buffer, 0, amount);
        }
    }


    /**
     * 校验签名1
     *
     * @param expected  期望信息
     * @param sign      签名
     * @param publicKey 公钥
     * @return 结果
     * @throws Exception 校验异常
     */
    public static boolean checkSign(String expected, byte[] sign, PublicKey publicKey) throws Exception {
        Signature signetCheck = Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
        signetCheck.initVerify(publicKey);
        signetCheck.update(expected.getBytes());
        return signetCheck.verify(sign);
    }



    /**
     * 验证签名2
     * @param preStr 待验证签名字符串
     * @param publicKeyStr 公钥字符串
     * @param rspSign 待验证签名值
     * @return 是否
     * @throws Exception
     */
    public static boolean verifySign(String preStr, String publicKeyStr, String rspSign)
            throws Exception {

        publicKeyStr = publicKeyStr.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").replace("\r", "").replace("\n", "").trim();
        //待验证签名值base64解码
        byte[] sign = Base64.decodeBase64(rspSign);
        String suite = "SHA256WithRSA";

        //初始化算法SHA256
        Signature  signature = Signature.getInstance(suite);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyStr));
        //初始化公钥+RSA
        KeyFactory keyFac = KeyFactory.getInstance("RSA");
        PublicKey pubKey = keyFac.generatePublic(keySpec);
        signature.initVerify(pubKey);

        //待签名字符串转byte数组使用UTF8
        byte[] msgBuf = preStr.getBytes("UTF8");
        signature.update(msgBuf);
        boolean bRst = signature.verify(sign);
        return bRst;
    }

}
